home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH10 / SRC / SPARSE2.CLS < prev    next >
Text File  |  1996-05-04  |  11KB  |  392 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "ObjSparseGrid"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. Private NumPts As Integer   ' # actual data values.
  11. Private Data() As Point3D   ' Actual data values.
  12.  
  13. Private ShowData As Boolean ' Draw the actual data?
  14.  
  15. Private grid As ObjGrid3D
  16. ' ************************************************
  17. ' Compute a weighted average of the y coordinates
  18. ' of the points with indices in best_i().
  19. ' ************************************************
  20. Sub WeightedAverage(x As Single, y As Single, z As Single, best_i() As Integer, num As Integer)
  21. Dim i As Integer
  22. Dim j As Integer
  23. Dim diffx As Single
  24. Dim diffz As Single
  25. Dim dist2(1 To 4) As Single
  26. Dim wgt As Single
  27. Dim tot As Single
  28.  
  29.     ' Compute the distance squared to each point.
  30.     For i = 1 To num
  31.         diffx = x - Data(best_i(i)).coord(1)
  32.         diffz = z - Data(best_i(i)).coord(3)
  33.         dist2(i) = diffx * diffx + diffz * diffz
  34.         If dist2(i) = 0 Then
  35.             y = Data(best_i(i)).coord(2)
  36.             Exit Sub
  37.         End If
  38.     Next i
  39.     
  40.     ' Compute the contribution due to each point.
  41.     y = 0
  42.     For i = 1 To num
  43.         ' Compute the weight for point i.
  44.         wgt = 1
  45.         For j = 1 To num
  46.             If j <> i Then
  47.                 wgt = wgt * dist2(j)
  48.             End If
  49.         Next j
  50.         y = y + wgt * Data(best_i(i)).coord(2)
  51.         tot = tot + wgt
  52.     Next i
  53.  
  54.     y = y / tot
  55. End Sub
  56.  
  57.  
  58.  
  59.  
  60. ' ************************************************
  61. ' Find the data point closest to the desired
  62. ' location.
  63. '
  64. ' If on_left is true the point must be to the left
  65. ' of (x, y).
  66. '
  67. ' If on_top is true the point must be above
  68. ' (x, y).
  69. ' ************************************************
  70. Sub FindNearestPoint(x As Single, z As Single, best_i As Integer, on_left As Boolean, on_top As Boolean)
  71. Dim i As Integer
  72. Dim best_dist2 As Single
  73. Dim diffx As Single
  74. Dim diffz As Single
  75. Dim dist2 As Single
  76.  
  77.     ' Start with the first data point.
  78.     best_i = 0
  79.     best_dist2 = 1000000
  80.     
  81.     ' See which points are closer.
  82.     For i = 1 To NumPts
  83.         ' See if the point satisfies on_left/on_top.
  84.         If (x < Data(i).coord(1)) = on_left And _
  85.            (z > Data(i).coord(3)) = on_top Then
  86.            
  87.             ' See if this point is closer than the
  88.             ' best one so far.
  89.             diffx = x - Data(i).coord(1)
  90.             diffz = z - Data(i).coord(3)
  91.             dist2 = diffx * diffx + diffz * diffz
  92.             If dist2 < best_dist2 Then
  93.                 best_i = i
  94.                 best_dist2 = dist2
  95.             End If
  96.         End If
  97.     Next i
  98. End Sub
  99.  
  100.  
  101.  
  102.  
  103.  
  104. ' ************************************************
  105. ' Create the grid values for display.
  106. '
  107. ' d_x and d_z tell how far apart to make the grid
  108. ' lines.
  109. ' ************************************************
  110. Public Sub InitializeGrid(Dx As Single, Dz As Single)
  111. Dim Xmin As Single
  112. Dim Xmax As Single
  113. Dim Zmin As Single
  114. Dim Zmax As Single
  115. Dim NumX As Integer
  116. Dim NumZ As Integer
  117. Dim wid As Single
  118. Dim hgt As Single
  119. Dim i As Integer
  120. Dim j As Integer
  121. Dim x As Single
  122. Dim y As Single
  123. Dim z As Single
  124. Dim best_i(1 To 4) As Integer
  125. Dim num_close As Integer
  126.  
  127.     ' Find the X and Z data bounds.
  128.     Xmin = Data(1).coord(1)
  129.     Xmax = Xmin
  130.     Zmin = Data(1).coord(3)
  131.     Zmax = Zmin
  132.     For i = 2 To NumPts
  133.         If Xmin > Data(i).coord(1) Then Xmin = Data(i).coord(1)
  134.         If Xmax < Data(i).coord(1) Then Xmax = Data(i).coord(1)
  135.         If Zmin > Data(i).coord(3) Then Zmin = Data(i).coord(3)
  136.         If Zmax < Data(i).coord(3) Then Zmax = Data(i).coord(3)
  137.     Next i
  138.  
  139.     ' Set the data boundaries.
  140.     wid = Xmax - Xmin
  141.     hgt = Zmax - Zmin
  142.     NumX = wid / Dx + 1
  143.     NumZ = hgt / Dz + 1
  144.     x = (wid - NumX * Dx) / 2
  145.     z = (hgt - NumZ * Dz) / 2
  146.     Xmin = Xmin - x
  147.     Xmax = Xmax + x
  148.     Zmin = Zmin - z
  149.     Zmax = Zmax + z
  150.     
  151.     ' Create the new grid object.
  152.     Set grid = New ObjGrid3D
  153.     grid.SetBounds Xmin, Dx, NumX, Zmin, Dz, NumZ
  154.  
  155.     ' Fill in data values.
  156.     x = Xmin
  157.     For i = 1 To NumX
  158.         z = Zmin
  159.         For j = 1 To NumZ
  160.             ' Find close points to the upper left,
  161.             ' upper right, lower left, and lower
  162.             ' right. Average them.
  163.             num_close = 1
  164.             FindNearestPoint x, z, best_i(num_close), True, True
  165.             If best_i(num_close) > 0 Then num_close = num_close + 1
  166.             
  167.             FindNearestPoint x, z, best_i(num_close), True, False
  168.             If best_i(num_close) > 0 Then num_close = num_close + 1
  169.             
  170.             FindNearestPoint x, z, best_i(num_close), False, True
  171.             If best_i(num_close) > 0 Then num_close = num_close + 1
  172.             
  173.             FindNearestPoint x, z, best_i(num_close), False, False
  174.             If best_i(num_close) > 0 Then num_close = num_close + 1
  175.             
  176.             WeightedAverage x, y, z, best_i, num_close - 1
  177.             
  178.             ' Add the value to the grid.
  179.             grid.SetValue x, y, z
  180.             z = z + Dz
  181.         Next j
  182.         x = x + Dx
  183.     Next i
  184. End Sub
  185.  
  186.  
  187.  
  188.  
  189.  
  190. ' ************************************************
  191. ' Set a data value.
  192. ' ************************************************
  193. Sub SetValue(x As Single, y As Single, z As Single)
  194.     NumPts = NumPts + 1
  195.     ReDim Preserve Data(1 To NumPts)
  196.     Data(NumPts).coord(1) = x
  197.     Data(NumPts).coord(2) = y
  198.     Data(NumPts).coord(3) = z
  199.     Data(NumPts).coord(4) = 1#
  200. End Sub
  201. ' ***********************************************
  202. ' Return a string indicating the object type.
  203. ' ***********************************************
  204. Property Get ObjectType() As String
  205.     ObjectType = "SPARSE_GRID"
  206. End Property
  207.  
  208.  
  209.  
  210. ' ***********************************************
  211. ' Fix the data coordinates at their transformed
  212. ' values.
  213. ' ***********************************************
  214. Public Sub FixPoints()
  215. Dim i As Integer
  216. Dim j As Integer
  217.     
  218.     ' Fix the grid points if the grid exists.
  219.     If Not grid Is Nothing Then grid.FixPoints
  220.  
  221.     ' Fix the original data.
  222.     For i = 1 To NumPts
  223.         For j = 1 To 3
  224.             Data(i).coord(j) = Data(i).trans(j)
  225.         Next j
  226.     Next i
  227. End Sub
  228.  
  229. ' ************************************************
  230. ' Apply a transformation matrix which may not
  231. ' contain 0, 0, 0, 1 in the last column to the
  232. ' object.
  233. ' ************************************************
  234. Public Sub ApplyFull(M() As Single)
  235. Dim i As Integer
  236.     
  237.     ' Apply the matrix to the grid if it exists.
  238.     If Not grid Is Nothing Then grid.ApplyFull M
  239.  
  240.     ' Apply the matrix to the sparse data.
  241.     For i = 1 To NumPts
  242.         m3ApplyFull Data(i).coord, M, Data(i).trans
  243.     Next i
  244. End Sub
  245.  
  246. ' ************************************************
  247. ' Apply a transformation matrix to the object.
  248. ' ************************************************
  249. Public Sub Apply(M() As Single)
  250. Dim i As Integer
  251.     
  252.     ' Apply the matrix to the grid if it exists.
  253.     If Not grid Is Nothing Then grid.Apply M
  254.  
  255.     ' Apply the matrix to the sparse data.
  256.     For i = 1 To NumPts
  257.         m3Apply Data(i).coord, M, Data(i).trans
  258.     Next i
  259. End Sub
  260.  
  261.  
  262. ' ************************************************
  263. ' Apply a nonlinear transformation.
  264. ' ************************************************
  265. Public Sub Distort(D As Object)
  266. Dim i As Integer
  267.     
  268.     ' Distort the grid if it exists.
  269.     If Not grid Is Nothing Then grid.Distort D
  270.  
  271.     ' Distort the sparse data.
  272.     For i = 1 To NumPts
  273.         D.Distort Data(i).coord(1), Data(i).coord(2), Data(i).coord(3)
  274.     Next i
  275. End Sub
  276.  
  277. ' ************************************************
  278. ' Write the sparse grid's grid object to a file
  279. ' using Write. The data can later be loaded into
  280. ' an ObjGrid3D object but not an ObjSparseGrid
  281. ' object.
  282. ' ************************************************
  283. Public Sub FileWriteGrid(filenum As Integer)
  284.     If Not grid Is Nothing Then grid.FileWrite filenum
  285. End Sub
  286. ' ************************************************
  287. ' Write a sparse grid to a file using Write.
  288. ' Begin with "SPARSE_GRID" to identify this object.
  289. ' ************************************************
  290. Public Sub FileWrite(filenum As Integer)
  291. Dim i As Integer
  292.  
  293.     ' Write basic information.
  294.     Write #filenum, "SPARSE_GRID", NumPts
  295.         
  296.     ' Write the data.
  297.     For i = 1 To NumPts
  298.         Write #filenum, Data(i).coord(1), _
  299.             Data(i).coord(2), Data(i).coord(3)
  300.     Next i
  301.     
  302.     ' Write grid spacing information.
  303.     If grid Is Nothing Then
  304.         Write #filenum, 0, 0
  305.     Else
  306.         Write #filenum, grid.Dx, grid.Dz
  307.     End If
  308. End Sub
  309.  
  310.  
  311.  
  312.  
  313.  
  314. ' ************************************************
  315. ' Draw the transformed points on a Form, Printer,
  316. ' or PictureBox.
  317. ' ************************************************
  318. Public Sub Draw(canvas As Object, Optional r As Variant)
  319. Dim i As Integer
  320.     
  321.     ' Draw the grid if it exists.
  322.     If Not grid Is Nothing Then grid.Draw canvas, r
  323.  
  324.     ' Draw the original data points if desired.
  325.     If ShowData Then
  326.         On Error Resume Next
  327.         For i = 1 To NumPts
  328.             canvas.Line (Data(i).trans(1) - 2, Data(i).trans(2) - 2)-Step(4, 4), vbRed
  329.             canvas.Line (Data(i).trans(1) + 2, Data(i).trans(2) - 2)-Step(-4, 4), vbRed
  330.         Next i
  331.     End If
  332. End Sub
  333.  
  334.  
  335.  
  336. ' ************************************************
  337. ' Read a sparse grid from a file using Input.
  338. ' Assume the "SPARSE_GRID" label has already been
  339. ' read.
  340. ' ************************************************
  341. Public Sub FileInput(filenum As Integer)
  342. Dim i As Integer
  343. Dim Dx As Single
  344. Dim Dz As Single
  345.  
  346.     ' Get the basic information.
  347.     Input #filenum, NumPts
  348.     
  349.     ' Allocate the Data array.
  350.     ReDim Data(1 To NumPts)
  351.     
  352.     ' Read the data.
  353.     For i = 1 To NumPts
  354.         Input #filenum, Data(i).coord(1), _
  355.             Data(i).coord(2), Data(i).coord(3)
  356.     Next i
  357.     
  358.     ' Read grid spacing information.
  359.     Input #filenum, Dx, Dz
  360.     
  361.     ' Initialize the grid data.
  362.     If Dx = 0 Then
  363.         Set grid = Nothing
  364.     Else
  365.         InitializeGrid Dx, Dz
  366.     End If
  367. End Sub
  368.  
  369.  
  370.  
  371. ' ************************************************
  372. ' Tell the user whether we're drawing the data.
  373. ' ************************************************
  374. Property Get ShowTrueData() As Boolean
  375.     ShowTrueData = ShowData
  376. End Property
  377.  
  378. ' ************************************************
  379. ' Let the user decide whether we should draw the
  380. ' actual data.
  381. ' ************************************************
  382. Property Let ShowTrueData(value As Boolean)
  383.     ShowData = value
  384. End Property
  385.  
  386.  
  387. Private Sub Class_Initialize()
  388.     Set grid = Nothing
  389. End Sub
  390.  
  391.  
  392.